// Implementation of the Socket class.


#include "Socket.h"
#include "string.h"
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include<iostream>


Socket::Socket() : m_sock ( -1 ) {
	memset ( &m_addr, 0, sizeof ( m_addr ) );

}

Socket::~Socket()
{
	if ( is_valid() )
		::close ( m_sock );
}

bool Socket::create()
{
	m_sock = socket ( AF_INET, SOCK_STREAM, 0);

	if ( ! is_valid() )
		return false;


	// TIME_WAIT - argh
	int on = 1;
	//setsockopt:closesocket(一般不会立即关闭socket,而是经TIME_WAIT的过程)时，后想重用该socket.
	if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
		return false;

	return true;

}



bool Socket::bind ( const int port )
{

	if ( ! is_valid() )
		return false;

	m_addr.sin_family = AF_INET;
	m_addr.sin_addr.s_addr = INADDR_ANY;
	m_addr.sin_port = htons ( port );

	int bind_return = ::bind ( m_sock, ( struct sockaddr * ) &m_addr, sizeof ( m_addr ) );

	if ( bind_return == -1 )
		return false;

	return true;
}


bool Socket::listen() const
{
	if ( ! is_valid() )
		return false;

	int listen_return = ::listen ( m_sock, MAXCONNECTIONS );


	if ( listen_return == -1 )
		return false;

	return true;
}


bool Socket::accept ( Socket& new_socket ) const
{
	int addr_length = sizeof ( new_socket.m_addr );
	new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &new_socket.m_addr, ( socklen_t * ) &addr_length );

	if ( new_socket.m_sock <= 0 )
		return false;
	else
		return true;
}


bool Socket::send ( const std::string s ) const
{
	int status = ::send ( m_sock, s.c_str(), s.size(), MSG_NOSIGNAL );
	if ( status == -1 )
      return false;
	else
      return true;
}


int Socket::recv ( std::string& s ) const
{
	char buf [ MAXRECV + 1 ];

	s = "";

	memset ( buf, 0, MAXRECV + 1 );

	int status = ::recv ( m_sock, buf, MAXRECV, 0 );

	if ( status == -1 )
	{
		std::cout << "status == -1   errno == " << errno << "  in Socket::recv\n";
		return 0;
    }
	else if ( status == 0 )
    {
		return 0;
    }
	else
    {
		s = buf;
		return status;
    }
}



bool Socket::connect ( const std::string host, const int port )
{
	if ( ! is_valid() ) return false;

	m_addr.sin_family = AF_INET;
	//将16位主机字节序转换为网络字节序
	m_addr.sin_port = htons ( port );
	//将点分十进制转换为二进制整数
	int status = inet_pton ( AF_INET, host.c_str(), &m_addr.sin_addr );

	if ( errno == EAFNOSUPPORT ) return false;

	status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );

	if ( status == 0 )
		return true;
	else
		return false;
}

//设置非阻塞I/O模式(即读写操作要么成功，要么立即返回错误，不会阻塞)
void Socket::set_non_blocking ( const bool b )
{

	int opts;
	//取得文件描述符状态flags,为open()的参数flags
	opts = fcntl ( m_sock, F_GETFL );

	if ( opts < 0 )
    {
		return;
    }

	if ( b )
		opts = ( opts | O_NONBLOCK );
	else
		opts = ( opts & ~O_NONBLOCK );
	//设置文件描述符的状态flags
	fcntl ( m_sock, F_SETFL,opts );
}